﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCitySessionModule.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-12
//    @Email			:    445267987@qq.com
//    @Module           :    NFCitySessionModule
//    @Desc             :
//
// -------------------------------------------------------------------------

#include "NFCitySessionModule.h"

#include "NFCityPlayer.h"
#include "NFCityPlayerUtil.h"
#include "NFCitySession.h"
#include "proto_access2zone.nanopb.h"
#include "NFServerComm/NFServerCommon/NFIServerMessageModule.h"
#include "NFLogicCommon/NFLogicBindRpcService.h"

NFCitySessionModule::NFCitySessionModule(NFIPluginManager* p):NFMMODynamicModule(p)
{
}

NFCitySessionModule::~NFCitySessionModule()
{
}

int NFCitySessionModule::Awake()
{
    FindModule<NFIMessageModule>()->AddRpcService<proto_ff::E_ACCESS2ZONE_QUERYUINREQ>(NF_ST_CITY_SERVER, this, &NFCitySessionModule::OnConnectionToken, true);
    FindModule<NFIMessageModule>()->AddRpcService<proto_ff::E_ACCESS2ZONE_START>(NF_ST_CITY_SERVER, this, &NFCitySessionModule::OnConnectionStart, true);
    FindModule<NFIMessageModule>()->AddRpcService<proto_ff::E_ZONE2ACCESS_SETROUTING>(NF_ST_CITY_SERVER, this, &NFCitySessionModule::OnSetRouting, true);

    RegisterServerMessage(NF_ST_CITY_SERVER, E_ACCESS2ZONE_TRANSFER);
    RegisterServerMessage(NF_ST_CITY_SERVER, E_ACCESS2ZONE_STOP, true);
    return 0;
}

int NFCitySessionModule::OnHandleServerMessage(uint32_t msgId, NFDataPackage& packet, uint64_t param1, uint64_t param2)
{
    if (!m_pObjPluginManager->IsInited(NF_ST_CITY_SERVER))
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "City Server not inited, drop client msg:{}", packet.ToString());
        return -1;
    }

    if (m_pObjPluginManager->IsServerStopping())
    {
        NFLogError(NF_LOG_DEFAULT, packet.nParam1, "City Server is Stopping, drop client msg:{}", packet.ToString());
        return -1;
    }

    switch (packet.nMsgId)
    {
        case E_ACCESS2ZONE_STOP:
        {
            OnConnectionStop(msgId, packet, param1, param2);
            break;
        }
        case E_ACCESS2ZONE_TRANSFER:
        {
            OnConnectionMessage(msgId, packet, param1, param2);
            break;
        }
        default:
        {
            NFLogError(NF_LOG_DEFAULT, 0, "Server MsgId:{} Register, But Not Handle, Package:{}", packet.nMsgId, packet.ToString());
            break;
        }
    }
    return 0;
}

int NFCitySessionModule::OnConnectionToken(proto_ff::Access2ZoneQueryUinReq& request, proto_ff::Access2ZoneQueryUinRes& respone, uint64_t proxyId, uint64_t clientId)
{
	NFLogDebug(NF_LOG_DEFAULT, clientId, "query uin, proxyId:{} clientId:{} ip:{}", proxyId, clientId, request.m_playerip());
	NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(NF_ST_CITY_SERVER);
	NF_ASSERT(pConfig);

	NFConnectionInfo stConnInfo;
	stConnInfo.m_iConnIdx = clientId;
	stConnInfo.m_iConnBusID = proxyId;
	proto_ff::AccountInfo accountInfo;
	bool ok = accountInfo.ParsePartialFromString(request.m_accountinfo());
	if (!ok)
	{
		LOGSVR_ERROR("Parse account_info From String failed:" << request.m_accountinfo());
		FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
		respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
		return 0;
	}

	NFLogDebug(NF_LOG_DEFAULT, clientId, "query uin, proxyId:{} clientId:{} accountInfo:{}", proxyId, clientId, accountInfo.Utf8DebugString());

	stConnInfo.m_szOpenID = accountInfo.account_id();
	stConnInfo.m_chPlatformType = accountInfo.account_type();

	LOGSVR_DEBUG("account_type=" << accountInfo.account_type() << ", openid=" << accountInfo.account_id()
		<< ", plat_type=" << accountInfo.plat_type() << ", token=" << request.m_token()
		<< ", ip=" << request.m_playerip());

	if (!proto_ff::eAccountType_IsValid(accountInfo.account_type()))
	{
		FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
		respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
		return 0;
	}

	if (accountInfo.account_type() != proto_ff::E_Account_Type_Local && !pConfig->IsNoToken)
	{
		if (accountInfo.plat_type() != proto_ff::E_PLAT_ANDROID &&
			accountInfo.plat_type() != proto_ff::E_PLAT_IOS)
		{
			FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
			respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
			return 0;
		}

		/*proto_ff::Proto_SvrPkg pkg_2;
		proto_ff::Proto_GARoleLoginAuthenticationReq* pGSReq = pkg_2.mutable_login_auth_req();

		pkg_2.set_svr_msg_id(proto_ff::E_GA_LOGIN_AUTHENTICATION_REQ);
		pGSReq->mutable_info()->set_connid(clientId);
		pGSReq->mutable_info()->set_conn_bus_id(proxyId);
		pGSReq->mutable_info()->mutable_info()->CopyFrom(accountInfo);
		pGSReq->set_token(request.m_token());*/
	}
	else
	{
		if (accountInfo.plat_type() != proto_ff::E_PLAT_ANDROID &&
			accountInfo.plat_type() != proto_ff::E_PLAT_IOS &&
			accountInfo.plat_type() != proto_ff::E_PLAT_WP)
		{
			FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
			respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
			return 0;
		}
		uint64_t uin = (uint64_t)BKDRHash(request.m_accountinfo().data(), request.m_accountinfo().size());

		LOGSVR_DEBUG("uin=" << uin << ", account_id=" << accountInfo.account_id().c_str() << ", len=" << strlen(accountInfo.account_id().c_str()));

		respone.set_m_uin(uin);
	}

	respone.set_m_ret(0);
	return 0;
}

int NFCitySessionModule::OnConnectionStart(proto_ff::Access2ZoneStart& request, proto_ff::Access2ZoneStartRes& respone, uint64_t proxyId, uint64_t clientId)
{
    NFLogDebug(NF_LOG_DEFAULT, clientId, "query uin, proxyId:{} clientId:{} ip:{}", proxyId, clientId, request.m_playerip());
    NFServerConfig* pConfig = FindModule<NFIConfigModule>()->GetAppConfig(NF_ST_CITY_SERVER);
    NF_ASSERT(pConfig);

    NFConnectionInfo stConnInfo;
    NFCitySession* pSession = nullptr;
    pSession = NFCitySession::CreateObj();
    if (pSession == nullptr)
    {
        FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
        respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
        NFLogError(NF_LOG_DEFAULT, clientId, "CIDRuntimeClass::CreateObj Failed");
        return 0;
    }

    stConnInfo.m_iConnIdx = clientId;
    stConnInfo.m_iConnBusID = proxyId;
    stConnInfo.m_iLoginIP = request.m_playerip();
    stConnInfo.m_ullUin = request.m_uin();
    stConnInfo.m_dwConnTime = NF_ADJUST_TIMENOW();

    proto_ff::CityAccountInfo accountInfo;
    bool ok = accountInfo.ParseFromArray(request.m_accountinfo().data(), request.m_accountinfo().size());
    if (!ok)
    {
        LOG_ERR(0, -1, "Parse account_info From String failed:{}", request.m_accountinfo());
        FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
        respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
        return 0;
    }

    NFCityPlayer* pPlayer = NFCityPlayerUtil::GetPlayerByRoleID(accountInfo.role_id());
    CHECK_NULL_WF(accountInfo.role_id(), pPlayer, "role_id:{} not exist!", accountInfo.role_id());
    if (pPlayer->GetToken() != accountInfo.token())
    {
        LOG_ERR(0, -1, "role_id:{} token not match!", accountInfo.role_id());
        FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);
        respone.set_m_ret(proto_ff::ERR_CODE_SYSTEM_ERROR);
        return 0;
    }

    pSession->Connect(&stConnInfo);

    respone.set_m_sessionobjid(pSession->GetGlobalId());
    respone.set_m_ret(0);
    return 0;
}

int NFCitySessionModule::OnConnectionStop(uint32_t msgId, NFDataPackage& packet, uint64_t proxyId, uint64_t clientId)
{
    proto_ff::Access2ZoneStop stop;
    CLIENT_MSG_PROCESS_WITH_PRINTF(packet, stop);

    uint32_t sessionId = stop.m_sessionobjid();
    NFCitySession* pSession = NFCitySession::GetObjByGlobalId(sessionId);
    CHECK_EXPR(pSession, -1, "CServerUtil::GetSessionObj Failed ID:{}", sessionId);

    uint64_t iConnIdx = pSession->GetConnIndex();
    uint32_t iConnBusID = pSession->GetConnBusId();
    CHECK_EXPR(clientId == iConnIdx, -1, "clientId:{} not match iConnIdx:{}", clientId, iConnIdx);
    CHECK_EXPR(proxyId == iConnBusID, -1, "proxyId:{} not match iConnBusID:{}", proxyId, iConnBusID);

    FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, proxyId, E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), clientId);

    pSession->DisConnect(SESSION_DISCONN_FROM_CLIENT, 0);

    return 0;
}

int NFCitySessionModule::OnConnectionMessage(uint32_t msgId, NFDataPackage& packet, uint64_t sessionId, uint64_t param2)
{
    NFrame::Proto_FramePkg pkg;
    CLIENT_MSG_PROCESS_WITH_PRINTF(packet, pkg);

    NFDataPackage tempPackage = packet;
    tempPackage.nMsgId = pkg.msg_id();
    tempPackage.nMsgLen = pkg.msg_data().size();
    tempPackage.nMsgSeq = pkg.disp_info().seq();
    tempPackage.mModuleId = pkg.module_id();
    tempPackage.nBuffer = (char*)pkg.msg_data().data();
    tempPackage.nParam1 = sessionId;
    FindModule<NFIMessageModule>()->OnHandleMessage(tempPackage);
    return 0;
}

int NFCitySessionModule::OnSetRouting(proto_ff::Access2ZoneSetRoutingRpcReq& request, proto_ff::Zone2AccessSetRoutingRpcRsp& respone, uint64_t proxyId, uint64_t clientId)
{
    return 0;
}

uint32_t NFCitySessionModule::BKDRHash(const void* key, int keyLen)
{
    uint8_t* pKey = NULL;
    uint8_t* pEnd = NULL;
    uint32_t seed = 131; //  31 131 1313 13131 131313 etc..
    uint32_t hash = 0;

    pEnd = (uint8_t*)key + keyLen;
    for (pKey = (uint8_t*)key; pKey != pEnd; pKey++)
    {
        hash = hash * seed + (*pKey);
    }

    return hash;
}
